/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fjala.softure.tree.sorted;

import java.util.Iterator;
import org.fjala.softure.tree.AbstractTree;
import org.fjala.softure.tree.Node;

/**
 * Implementation that keep a sorted tree always.
 * 
 * @author Dann Meneses
 * @param <E> Type of element that this tree contains.
 */
public class SortedBinaryTree<E extends Comparable<E>> extends AbstractTree<E> {

    private TreeSorter<E> sorter;
    
    /**
     * Constructor that set the root node of the tree.
     * 
     * @param root tree root
     */
    public SortedBinaryTree(BinaryNode<E> root) {
        this.root = root;
        sorter = new TreeSorter<E>();
    }

    /**
     * Default constructor.
     */
    public SortedBinaryTree() {
        sorter = new TreeSorter<E>();
    }

    @Override
    public void replace(E oldElement, E newElement) {
        Node<E> search = search(oldElement);
        search.setData(newElement);
        SortedBinaryTree<E> sortedTree = sorter.sort(this);
        root = sortedTree.getRoot();
    }

    @Override
    public boolean add(E e) {
        if(e == null) {
            return false;
        }
        
        if (root == null) {
            root = new BinaryNode<E>(e, null);
        } else {
            root.addChild(new BinaryNode<E>(e, root));
        }
        return true;
    }

    @Override
    public boolean add(Node<E> parent, E element) {
        parent.addChild(new BinaryNode<E>(element, parent));
        return true;
    }

    @Override
    public int size() {
        Iterator<E> iterator = iterator();
        int res = 0;
        while (iterator.hasNext()) {
            res++;
            iterator.next();
        }
        return res;
    }

    @Override
    public Iterator<E> iterator() {
        return new SortedBinaryTreeIterator<E>((BinaryNode<E>)root);
    }
    
    public Node<E> search(E element){
        SortedBinaryTreeIterator<E> iterator = 
                new SortedBinaryTreeIterator<E>((BinaryNode<E>)root);
        
        while(iterator.hasNext()){
            E next = iterator.next();
            if(element.compareTo(next) == 0) {
                return iterator.getCurrent();
            }
        }
        
        return null;
    }
}
